﻿using System;

namespace _117_可空类型_运算符提升
{
    class Program
    {
        static void Main(string[] args)
        {
            //Nullable<T>结构体并没有定义诸如<、>或者==的运算符。尽管如此，下面的代码仍然能够正常编译和执行：
            /*
            int? x = 5;
            int? y = 10;
            bool b = x < y; // 结构为真
            */
            //这是因为编译器会从实际值类型盗取或“提升”小于运算符。在语义上，它会将前面的比较表达式转换成以下语句：
            //bool b = (x.HasValue && y.HasValue) ? (x.Value < y.Value) : false;
            //换句话说，如果x和y都有值，那么它会通过int的小于运算符比较；否则，它会返回false。

            //运算符提升表示可以隐式地使用T的运算符来处理T?。可以定义专门针对T?处理的运算符来实现特殊用途的空值操作，但是在大多数情况中，最好通过编译器来自动地应用系统的空值逻辑。
            //下面是一些应用示例：
            int? x = 5;
            int? y = null;
            //等于运算符示例
            Console.WriteLine(x == y); //结果为假
            Console.WriteLine(x == null); //结果为假
            Console.WriteLine(x == 5); //结果为真
            Console.WriteLine(y == null); //结果为真
            Console.WriteLine(y == 5); //结果为假
            Console.WriteLine(y != 5); //结果为真
            //关系运算符示例
            Console.WriteLine(x < 6); //结果为真
            Console.WriteLine(y < 6); //结果为假
            Console.WriteLine(y > 6); //结果为假
            //其他运算符示例
            Console.WriteLine(x + 5); // 10
            Console.WriteLine(x + y); // null(指向空行)


            //编译器会基于运算符类来执行空值逻辑。


            //1.等于运算符（==和!=）
            //提升等于运算符处理空值的方式和引用类型相似。这意味着两个空值是相等的：
            Console.WriteLine(null == null); //结果为真
            Console.WriteLine((bool?)null == (bool?)null); //结果为真
            //而且：
            //    如果只有一个操作数为空，那么结果不相等。
            //    如果两个操作数都不为空，那么比较它们的Value。


            //2.关系运算符（<、<=、>=、>）
            //关系运算符的运算原则表明空值操作数的比较是无意义的。这意味着比较两个空值或者比较一个空值与一个非空值的结果都是false。
            bool b = x < y;
            // 转换：
            bool b1 = (x == null || y == null) ? false : (x.Value < y.Value);
            //b为假（假设x为5而y为null）


            //3.其他运算符（+、-、*、/、%、|、^、<<、>>、+、++、--、!、~）
            //如果任意一个操作数为空，那么这些运算符都会返回空值。这类似于SQL采用的模式。
            int? c = x + y;
            //转换：
            int? c1 = (x == null) || (y == null) ? null : (int?)(x.Value + y.Value);
            // c为null（假设x为5，y为null）
            //唯一例外的是计算bool?的&和|运算符


            //4.混合使用可空和不可空运算符
            //可以混合使用可空和不可空类型，这是因为T与T?之间存在隐式转换机制：
            int? a4 = null;
            int b4 = 2;
            int? c4 = a4 + b4; // c为null - 相等于 a+(int?)b

            Console.ReadKey();
        }
    }
}
